home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Processes / MP Threaded Sort / Sprocket / Lib / SprocketMain.cp < prev    next >
Encoding:
Text File  |  1997-03-13  |  16.4 KB  |  649 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.         <11>    11/16/94    DRF        Added an explicit #include <Traps.h> for latest universal
  13.                                     headers. Also killed off a CFront warning.
  14.         <10>    11/12/94    DRF        Revised QuickDrawGX initialization based on changes made by Jon
  15.                                     Summer. We now use a 'gasz' resource to setup the size of the
  16.                                     graphics heap. Also we are now always TSM aware, not just when
  17.                                     TSMTE is around.
  18.          <9>     11/8/94    DRF        Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  19.                                     exists. Also, stop openning up the preferences file here.
  20.          <8>     9/27/94    DRF         AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  21.                                      and eliminated HandleUpdate.
  22.          <7>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  23.                                     Conditionalized AOCE support. Also made changes to
  24.                                     TSMEventWrapper to be more like the code in InlineInputSample.
  25.          <6>      9/8/94    DRF        Add HiliteMenu(0) calls after calls to menu handling code
  26.                                     because TSMMenuSelect doesn’t do it. Also reorganized some GX
  27.                                     stuff: allocate and release a graphicsclient (Cam claims this
  28.                                     works on his machine), and turn on all the graphics errors and
  29.                                     notices if qDebug is set.
  30.          <5>      9/7/94    DRF        Rearrange YieldToAnyThread calls to make quitting faster.
  31.          <4>      9/4/94    DRF        Rearrange local variables in HandleMouseDown.
  32.          <3>      9/1/94    DRF        Stop including "MailableWindow.h" here.
  33.          <2>      9/1/94    DRF        More fixes for inline input, but we’re not really done yet.
  34.  */
  35.  
  36. #include "Sprocket.h"
  37.  
  38. #include <limits.h>        //    For LONG_MAX
  39. #include <Multiprocessing.h>
  40. #include <Fonts.h>
  41. #include <Devices.h>
  42. #include <Gestalt.h>
  43. #include <DiskInit.h>
  44. #include <Threads.h>
  45. #include <CodeFragments.h>    //    for kUnresolvedSymbolAddress
  46. #include <Traps.h>
  47. #include <lowmem.h>
  48. #if    qInlineInputAware
  49. #include <TextServices.h>
  50. #include <TSMTE.h>
  51. #endif
  52.  
  53. #if    qUseQuickDrawGX
  54. #include <graphics macintosh.h>
  55. #include <graphics routines.h>
  56. #include <graphics libraries.h>
  57. #include <PrintingManager.h>
  58. #endif
  59.  
  60. #include "StandardMenus.h"
  61. #include "Window.h"
  62. #include "SplashWindow.h"
  63. #include "AppleEventHandling.h"
  64.  
  65.  
  66. //    Function Prototypes
  67.  
  68. void    main(void);
  69. void    MainEventLoop(void);
  70.  
  71. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  72. void    HandleClose(WindowPtr aWindow);
  73.  
  74.  
  75. //    Globals
  76.  
  77. Boolean                gDone = false;
  78. Boolean                gMenuBarNeedsUpdate = true;
  79.  
  80. Boolean                gHasColorQuickdraw = false;
  81. Boolean                gHasThreadManager = false;
  82. Boolean                gHasDragManager = false;
  83. Boolean                gHasAppleScript = false;
  84. Boolean                gHasDisplayManager = false;
  85.  
  86. GrafPtr                gWindowManagerPort;
  87. Rect                gDeskRectangle;
  88. RgnHandle            gMouseRegion = nil;
  89.  
  90. short                gPreferencesRsrcRefNum;
  91.  
  92. #if    qAOCEAware
  93. Boolean                gHasAOCE = false;
  94. #endif
  95.  
  96. #if    qInlineInputAware
  97. Boolean                gHasTextServices = false;
  98. Boolean                gHasTSMTE = false;
  99.  
  100. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  101.  
  102. #endif
  103.  
  104. #if    qUseQuickDrawGX
  105. Boolean                gHasQuickDrawGX = false;
  106. long                gQuickDrawGXVersion = 0;
  107. long                gQuickDrawGXPrintingVersion = 0;
  108. gxGraphicsClient    gQuickDrawGXClient;
  109. #endif
  110.  
  111.  
  112. //    Values that can be adjusted by other application code to change
  113. //    the behavior of the MainEventLoop.
  114. //
  115. //    Rules of thumb:
  116. //
  117. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  118. //            The application has many threads running that need time
  119. //
  120. //        Decrease gXXXRunQuantum when:
  121. //            Sending AppleEvents to other applications
  122. //            Launching other applications
  123. //            Running in the background
  124.  
  125. unsigned long    gForegroundRunQuantum = 0;
  126. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  127. unsigned long    gBackgroundRunQuantum = 0;
  128. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  129.  
  130.  
  131. //    Globals used to “tune” the performance of MainEventLoop
  132. //    (assume we’ll be starting in the foreground)
  133.  
  134. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  135. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  136.  
  137. #ifdef    powerc
  138. #ifndef    __MWERKS__
  139. QDGlobals    qd;
  140. #endif
  141. #endif
  142.  
  143. void
  144. main(void)
  145.     {
  146.     long        feature;
  147.  
  148.     MaxApplZone();
  149.     MoreMasters();
  150.     MoreMasters();
  151.     MoreMasters();
  152.     MoreMasters();
  153.  
  154.     InitGraf(&qd.thePort);    
  155.     InitFonts();
  156.     InitWindows();
  157.     InitMenus();
  158.     TEInit();
  159.     InitDialogs(nil);
  160.  
  161.  
  162.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  163.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  164.  
  165.     
  166.     TSplashWindow * splashWindow = new TSplashWindow;
  167.  
  168.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  169.     
  170. #if    qUseQuickDrawGX
  171.     //    Check for and initialize QuickDrawGX
  172.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  173.         {
  174.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  175.             {
  176. #ifdef    powerc
  177.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  178. #endif
  179.             gHasQuickDrawGX = true;
  180.             }
  181.         }
  182.  
  183.     if (gHasQuickDrawGX)
  184.         {
  185.         // Initialize the graphics and printing environments.
  186.         //    For additional details see "IM: QD GX Environment & Utilities."
  187.         
  188.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  189.         //    GX uses the first long word of that resource as the graphics heap size.
  190.         //    To determine the memory requirements of your graphics client heap see:
  191.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  192.         
  193.         //    NOTE:    If your application does not provide this resource,
  194.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  195.  
  196.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  197.         if (gQuickDrawGXClient)
  198.             {
  199.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  200.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  201.             //            while we have a chance to deal with things nicely.
  202.             //
  203.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  204.             
  205.             GXEnterGraphics();
  206.  
  207.             if (GXGetGraphicsError(nil) == noErr)
  208.                 {
  209. #if    qUseQuickDrawGXDebugging
  210.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  211.  
  212.                 //    NOTES from Jon Summers:
  213.                 //    As you increase the amount of validation, drawing speed will SLOW
  214.                 //    down due to all of the internal checking. Also, if you play with
  215.                 //    settings enough validation seems to become inconsistent
  216.  
  217.                 GXSetValidation(    //    gxInternalValidation    |
  218.                                     //    gxAllObjectValidation    |
  219.                                     //    gxApHeapValidation        |
  220.                                         gxPublicValidation);        // check parameters to public routines
  221.  
  222.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  223.                 //    If you don't have the debugging version installed, these functions will not work. 
  224.  
  225.                 SetGraphicsLibraryErrors();
  226.                 SetGraphicsLibraryNotices();    
  227. #endif
  228.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  229.                     {
  230.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  231.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  232.                     
  233.                     if (gQuickDrawGXClient)
  234.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  235.                     gHasQuickDrawGX = false;
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.  
  241.     if (gQuickDrawGXClient)
  242.         InitCommonColors();        // Initialize the CommonColors Library.
  243. #if    qRequireQuickDrawGX
  244.     else
  245.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  246. #endif    //    qRequireQuickDrawGX
  247. #endif    //    qUseQuickDrawGX
  248.  
  249.  
  250.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  251.         (feature & (1 << gestaltAppleEventsPresent)))
  252.         {
  253.         //    Figure out if we need to do AppleEvent recording
  254.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  255.         }
  256.     else
  257.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  258.  
  259. #if    qInlineInputAware
  260.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  261.         {
  262.         gHasTextServices = true;
  263.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  264.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  265.  
  266.         if (InitTSMAwareApplication() != noErr)
  267.             {
  268.             gHasTextServices = false;
  269.             gHasTSMTE = false;
  270.             }
  271.         }
  272.  
  273. #endif
  274.  
  275.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  276.         {
  277. #ifdef    powerc
  278.         //    If running on a PowerPC, make sure that we not only have the
  279.         //    68K Thread Manager, but also the PowerPC shared library, too.
  280.         //    Because of the wonders of weak linking and out of memory errors
  281.         //    we need to also check to make sure that an entrypoint in the library
  282.         //    is there, too. 
  283.         if (long(NewThread) != kUnresolvedCFragSymbolAddress)
  284.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  285. #else
  286.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  287. #endif
  288.         }
  289.  
  290. #if    qRequireThreadManager
  291.     if (gHasThreadManager == false)
  292.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  293. #endif
  294.  
  295.     //    Check for and install Drag Manager callbacks
  296.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  297.         {
  298. #ifdef    powerc
  299.         //    If running on a PowerPC, make sure that we not only have the
  300.         //    68K Drag Manager, but also the PowerPC shared library, too.
  301.         if (long(NewDrag) != kUnresolvedCFragSymbolAddress)
  302.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  303. #else
  304.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  305. #endif
  306.  
  307.         if (gHasDragManager)
  308.             {
  309.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  310.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  311.             }
  312.         }
  313.  
  314.     //    Check for Display Manager
  315.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  316.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  317.  
  318. #if    qAOCEAware    
  319.     //    Check for and initialize AOCE Standard Mail package if it exists
  320.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  321.         {
  322. #ifdef    powerc
  323.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  324.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  325. #else
  326.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  327. #endif
  328.         }
  329. #endif
  330.  
  331.     //    Install our AppleEvent Handlers
  332.     InstallAppleEventHandlers();
  333.  
  334.     //    Setup desktop rectangle for dragging windows around            
  335.     GetWMgrPort(&gWindowManagerPort);
  336.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  337.  
  338.     //    Get the default menubar
  339.     SetMenuBar(GetNewMBar(rMenuBar));
  340.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  341.  
  342.     // Add fonts to the font menu if it installed
  343.     if (GetMenuHandle(mFont))
  344.         AppendResMenu(GetMenuHandle(mFont),'FONT');
  345.     
  346.     if (SetupApplication() == noErr)
  347.         {
  348.         delete    splashWindow;    //    get rid of the splash screen
  349.         
  350.         if (!MPLibraryIsLoaded())     { //Don't allow MP tasks
  351.             DisableItem(GetMenuHandle(257),7);
  352.         }
  353.         MainEventLoop();
  354.         TearDownApplication();
  355.         }
  356.  
  357.  
  358. #if    qInlineInputAware
  359.     if (gHasTextServices)
  360.         (void) CloseTSMAwareApplication();
  361. #endif
  362.         
  363. #if    qUseQuickDrawGX
  364.     //    Tear down QuickDrawGX
  365.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  366.         {
  367.         DisposeCommonColors();
  368.         GXExitPrinting();        // Close the new printing mgr. 
  369.         GXExitGraphics();        // Deallocate all of the default structures
  370.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  371.         }
  372. #endif
  373.     }
  374.  
  375.  
  376. void
  377. MainEventLoop(void)
  378.     {
  379.     EventRecord        anEvent;
  380.     unsigned long    nextTimeToCheckForEvents = 0;
  381.     
  382.     while (!gDone)
  383.         {
  384.         if (gMenuBarNeedsUpdate)
  385.             {
  386.             gMenuBarNeedsUpdate = false;
  387.             DrawMenuBar();
  388.             }
  389.  
  390.         if (gHasThreadManager)
  391.             YieldToAnyThread();
  392.  
  393.         if ((gRunQuantum == 0) ||
  394.             (TickCount() > nextTimeToCheckForEvents))
  395.             {
  396.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  397.             
  398.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  399.                         
  400. #if    qInlineInputAware
  401.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  402.                 {
  403.                 }
  404.             else
  405. #endif
  406.                 HandleEvent(&anEvent);
  407.             }
  408.         }
  409.     }
  410.  
  411. #if    qInlineInputAware
  412.  
  413. Boolean
  414. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  415.     {
  416.     short        oldFont;
  417.     ScriptCode    keyboardScript;
  418.     Boolean        didTSMHandleTheEvent = false;
  419.  
  420.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  421.     //    and is related to working around a bug in Kotoeri, one of the
  422.     //    Japanese Input methods when operating in a mixed script
  423.     //    environment (e.g., Japanese Language Kit)
  424.     
  425.     // make sure we have a port and it's not the Window Manager port
  426.     if (qd.thePort != nil)
  427.         {
  428.         oldFont            = qd.thePort->txFont;
  429.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  430.  
  431.         if (FontToScript(oldFont) != keyboardScript)
  432.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  433.         }
  434.  
  435.     didTSMHandleTheEvent = TSMEvent(anEvent);
  436.     
  437.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  438.  
  439.     return didTSMHandleTheEvent;
  440.     }
  441.  
  442. #endif    
  443.  
  444.  
  445.  
  446. void
  447. HandleEvent(EventRecord *anEvent)
  448.     {
  449.     TWindow    * wobj;
  450.     
  451.     if (anEvent->what != updateEvt)
  452.         wobj = GetWindowObject(FrontNonFloatingWindow());
  453.     else
  454.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  455.  
  456.     if (wobj != nil)
  457. #if    qInlineInputAware
  458.         // give text services a chance to set the cursor shape
  459.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  460.             ;    // do nothing, TSM did it for me
  461.         else    
  462. #endif
  463.             wobj->AdjustCursor(anEvent);
  464.     
  465.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  466.         return;
  467.         
  468.     else switch (anEvent->what)
  469.         {
  470.         case    nullEvent:
  471.             WindowPtr aWindow = LMGetWindowList();
  472.             
  473.             while ( aWindow )
  474.             {
  475.                 wobj = GetWindowObject((WindowPtr) aWindow);
  476.                 if (wobj != nil)
  477.                     wobj->Idle(anEvent);
  478.                 aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;
  479.             }
  480.             break;
  481.             
  482.         case    mouseDown:
  483.             HandleMouseDown(wobj,anEvent);
  484.             break;
  485.         
  486.         case    keyDown:
  487.         case    autoKey:
  488.             if (anEvent->modifiers & cmdKey)
  489.                 {
  490.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  491. #if    qInlineInputAware
  492.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  493. #endif
  494.                     HandleMenu(wobj,menuResult);
  495.                 HiliteMenu(0);
  496.                 }
  497.             else if (wobj != nil)
  498.                 wobj->KeyDown(anEvent);
  499.             break;
  500.             
  501.         case    updateEvt:
  502.             {
  503.             GrafPtr        oldPort;
  504.             WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  505.                 
  506.             GetPort(&oldPort);
  507.             SetPort(aWindow);
  508.             BeginUpdate(aWindow);
  509.             if (wobj != nil)
  510.                 wobj->Draw();
  511.             EndUpdate(aWindow);
  512.             SetPort(oldPort);
  513.             }
  514.             break;
  515.             
  516.         case diskEvt:
  517.             if (anEvent->message >> 16)
  518.                 {
  519.                 static    Point    where = {50,50};
  520.                 (void) DIBadMount(where,anEvent->message);
  521.                 }
  522.             break;
  523.                 
  524.         case    osEvt:
  525.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  526.                 {
  527.                 case    mouseMovedMessage:
  528.                     break;
  529.                     
  530.                 case    suspendResumeMessage:                    
  531.  
  532.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  533.  
  534.                     if (anEvent->message & resumeFlag)
  535.                         {
  536.                         if (anEvent->message & convertClipboardFlag)
  537.                             ReadLocalClipboardFromScrap();
  538.  
  539.                         gRunQuantum = gForegroundRunQuantum;
  540.                         gSleepQuantum = gForegroundSleepQuantum;
  541.                         }
  542.                     else
  543.                         {
  544.                         if (anEvent->message & convertClipboardFlag)
  545.                             WriteLocalClipboardToScrap();
  546.                         gRunQuantum = gBackgroundRunQuantum;
  547.                         gSleepQuantum = gBackgroundSleepQuantum;
  548.                         }
  549.  
  550.                     break;
  551.                 }
  552.             break;
  553.         
  554.         case    kHighLevelEvent:
  555.             (void) AEProcessAppleEvent(anEvent);
  556.             break;
  557.             
  558.         default:
  559.             break;
  560.         }
  561.     }
  562.  
  563. void
  564. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  565.     {
  566.     WindowPtr    aWindow;
  567.     TWindow        *wobj;
  568.     short        partCode;
  569.  
  570.     partCode = FindWindow(anEvent->where,&aWindow);
  571.     wobj = GetWindowObject(aWindow);
  572.     switch(partCode)
  573.         {
  574.         case    inMenuBar:
  575.             long    menuResult = MenuSelect(anEvent->where);
  576. #if    qInlineInputAware
  577.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  578. #endif
  579.                 HandleMenu(topWindowObj,menuResult);
  580.             HiliteMenu(0);
  581.             break;
  582.             
  583.         case    inSysWindow:
  584.             SystemClick(anEvent,aWindow);
  585.             break;
  586.             
  587.         case    inContent:
  588.             if (wobj)
  589.                 {
  590.                 GrafPtr    oldPort;
  591.                 
  592.                 GetPort(&oldPort);
  593.                 SetPort(aWindow);
  594.                 GlobalToLocal(&anEvent->where);
  595.                 wobj->Click(anEvent);
  596.                 SetPort(aWindow);
  597.                 }
  598.             break;
  599.             
  600.         case    inDrag:
  601.             if (wobj)
  602.                 wobj->Drag(anEvent->where);
  603.             break;
  604.             
  605.         case    inGrow:
  606.             if (wobj)
  607.                 wobj->Grow(anEvent->where);
  608.             break;
  609.             
  610.         case    inGoAway:
  611.             if (TrackGoAway(aWindow,anEvent->where))
  612.                 HandleClose(aWindow);
  613.             break;
  614.  
  615.         case    inZoomIn:
  616.         case    inZoomOut:
  617.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  618.                 wobj->Zoom(partCode);
  619.             break;
  620.             
  621.         default:
  622.             break;
  623.         }
  624.     }
  625.     
  626.  
  627. void
  628. HandleClose(WindowPtr aWindow)
  629.     {
  630.     short    windowKind;
  631.     TWindow    *wobj;
  632.     
  633.     if (aWindow)
  634.         {
  635.         windowKind = ((WindowPeek) aWindow)->windowKind;
  636.         if (windowKind < 0)
  637.             {
  638.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  639.             }
  640.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  641.                     wobj->CanClose() &&
  642.                     wobj->Close() &&
  643.                     wobj->DeleteAfterClose())
  644.             {
  645.             delete wobj;
  646.             }
  647.         }
  648.     }
  649.